package com.gemserk.infraestructure.lwjglmavenizer;



import groovy.util.CliBuilder;
import groovyx.net.http.HTTPBuilder 

import java.io.File;

import org.apache.commons.io.FileUtils;

public class Mavenizer {
	
	public static File createTempDirectory(String prefix){
		final File temp;
		
		temp = File.createTempFile(prefix, Long.toString(System.nanoTime()));
		
		if(!(temp.delete())) {
			throw new IOException("Could not delete temp file: " + temp.getAbsolutePath());
		}
		
		if(!(temp.mkdir())) {
			throw new IOException("Could not create temp directory: " + temp.getAbsolutePath());
		}
		
		return (temp);
	}
	
	public static File makeRelativeTo(File file, File relativeTo){
		return new File(file.getAbsolutePath().substring(relativeTo.getAbsolutePath().length()))
	}
	
	
	
	public static void main(String[] args) {
		
		CliBuilder cli = new CliBuilder(usage:"LWJGLMavenizer: you must select a workDir which has the binaries, javadoc, and sources zip for lwjgl")
		
		
		cli.with {
			
			d(longOpt:'workDir', args:1, argName:'work directory', 'Directory which containes full lwjgl zip distribution', required:true)
			v(longOpt:'version', args:1, argName:'version','Maven version of generated artifacts',required:false)
			s(longOpt:'snapshot','Force the autodetected version to be SNAPSHOT',required:false)
			r(longOpt:'repoUrl', args:1, argName:'repoUrl','URL of maven repository',required:false)
			i(longOpt:'repoId', args:1, argName:'repoId','ID of maven repository',required:false)
			w(longOpt:'download',args:1,argName:'version from sourceforge','Download files from sourceforge')
		}
		
		
		
		def options = cli.parse(args)
		
		if(!options){
			System.exit(0)
		}
		
		
		File workDir = new File(options.d)
		
		if(!workDir.exists() || (!workDir.isDirectory())){
			System.out.println("WorkDir does not exist or is not a directory - $workDir");
			System.exit(1)
		}
		
		
		def repoUrl = options.r ?: "REPOURL"
		def repoId = options.i ?: "REPOID"
		
		File targetBaseFile = new File(workDir,"result")
		
		def sourceForgeVersion = options.w
		
		File lwjglBinaryBaseFile
		File lwjglSourceBaseFile 
		File lwjglJavadocBaseFile 
		
		
		def fileFinder = { String base ->
			return { File file ->
				String name = file.getName()
				def lastIndex = name.lastIndexOf("-")
				if(lastIndex==-1)
					return false
				def baseToCompare = name.substring(0, lastIndex)
				return base.equals(baseToCompare)
			}
		}
		
		def fileVersion = { File file ->
			String name = file.getName()
			def lastIndexOfDash = name.lastIndexOf("-")
			def lastIndexOfPeriod = name.lastIndexOf(".")
			
			return name.substring(lastIndexOfDash + 1, lastIndexOfPeriod)
		}
		
		
		def  http = new  HTTPBuilder()
		
		if(sourceForgeVersion){
			println "Downloading from sourceforge - version: $sourceForgeVersion"
			
			
			def downloader = new HTTPDownloader()
			try{
				lwjglBinaryBaseFile = new File(workDir,"lwjgl-${sourceForgeVersion}.zip")
				lwjglSourceBaseFile = new File(workDir,"lwjgl-source-${sourceForgeVersion}.zip")
				lwjglJavadocBaseFile = new File(workDir,"lwjgl-docs-${sourceForgeVersion}.zip")
				def uri = { version, file -> "http://sourceforge.net/projects/java-game-lib/files/Official%20Releases/LWJGL%20${version}/${file}-${version}.zip/download" }
				
				downloader.downloadFile(http,uri(sourceForgeVersion,"lwjgl"),lwjglBinaryBaseFile)
				downloader.downloadFile(http,uri(sourceForgeVersion,"lwjgl-source"),lwjglSourceBaseFile)
				downloader.downloadFile(http,uri(sourceForgeVersion,"lwjgl-docs"),lwjglJavadocBaseFile)
			}finally {
				http.shutdown()
			}
		} else  {
			def childrenDirs = workDir.listFiles()
			
			
			lwjglBinaryBaseFile = childrenDirs.find(fileFinder("lwjgl"))
			lwjglSourceBaseFile = childrenDirs.find(fileFinder("lwjgl-source"))
			lwjglJavadocBaseFile = childrenDirs.find(fileFinder("lwjgl-docs"))
		}
		
		
		if(targetBaseFile.exists()){
			if(!targetBaseFile.isDirectory()){
				System.out.println("TargetDir is not a directory");
				System.exit(1)
			}
		} else {
			targetBaseFile.mkdirs()
		}
		
		if(lwjglBinaryBaseFile== null || !lwjglBinaryBaseFile.exists() || (!lwjglBinaryBaseFile.isFile() || !lwjglBinaryBaseFile.getAbsolutePath().endsWith(".zip"))){
			System.out.println("binaries distribution does not exist or is not a zip file");
			System.exit(1)
		}
		
		if(lwjglSourceBaseFile== null || !lwjglSourceBaseFile.exists() || (!lwjglSourceBaseFile.isFile() || !lwjglSourceBaseFile.getAbsolutePath().endsWith(".zip"))){
			System.out.println("sources distribution does not exist or is not a zip file");
			System.exit(1)
		}
		
		if(lwjglJavadocBaseFile== null || !lwjglJavadocBaseFile.exists() || (!lwjglJavadocBaseFile.isFile() || !lwjglJavadocBaseFile.getAbsolutePath().endsWith(".zip"))){
			System.out.println("javadoc distribution does not exist or is not a zip file");
			System.exit(1)
		}
		
		def versionFromFile = fileVersion(lwjglBinaryBaseFile)
		if(![lwjglBinaryBaseFile,lwjglSourceBaseFile,lwjglJavadocBaseFile].every { file ->	versionFromFile == fileVersion(file)}){
			System.out.println("Not all files have the same version");
		}
		
		
		
		def version = options.v ?: (!options.s ? versionFromFile : versionFromFile + "-SNAPSHOT")
		
		System.out.println("Generating Version " + version);
		new Mavenizer().mavenizeParseCommands(workDir,targetBaseFile , lwjglBinaryBaseFile , lwjglSourceBaseFile, lwjglJavadocBaseFile , version, repoUrl, repoId)
	}
	
	public void mavenizeParseCommands(File workDir, File targetBase, File lwjglBinaryBase, File lwjglSourceBase,File lwjglJavadocBase, version, repoUrl, repoId){
		
		File tempDir = new File(workDir,"tmp")
		
		File binaries = new File(tempDir,"binaries")
		
		new ZipUtils().unzip(lwjglBinaryBase, binaries) 
		def childrenDirs = binaries.list()
		if(childrenDirs.size() == 0)
			throw new Exception("Empty zip $lwjglBinaryBase")
		
		if(childrenDirs.size() == 1){
			
			binaries = new File(binaries,childrenDirs[0])
		} 
		
		File sources = new File(tempDir,"sources")
		new ZipUtils().unzip(lwjglSourceBase, sources)
		childrenDirs = sources.list()
		if(childrenDirs.size() == 0)
			throw new Exception("Empty zip $lwjglSourceBase")
		
		File javadoc = new File(tempDir,"javadoc")
		new ZipUtils().unzip(lwjglJavadocBase, javadoc)
		childrenDirs = javadoc.list()
		if(childrenDirs.size() == 0)
			throw new Exception("Empty zip $lwjglJavadocBase")
		
		mavenize(workDir,targetBase, binaries, sources, javadoc, version, repoUrl, repoId)
	}
	
	public void mavenize(File workDir, File targetBaseFile, File lwjglBinaryBase, File lwjglSourceBase, File lwjglJavadocBase, lwjglVersion, repoUrl, repoId){
		println BasicConstants.SOS;
		println BasicConstants.basePath;
		
		
		targetBaseFile.mkdirs()
		
		
		POMBuilder pomBuilder = new POMBuilder();
		
		
		def sourceBase= lwjglSourceBase
		def javadocBase = lwjglJavadocBase
		def jarsBase = new File(lwjglBinaryBase,"jar")
		def nativesBase =  new File(lwjglBinaryBase,"native")
		
		def logs = []
		def deployCommands = []
		def installCommands = []
		
		BasicConstants.libs.each{ library ->
			
			def attached = []
			
			def natives = BasicConstants.natives[(library)];
			if(natives!=null){
				BasicConstants.SOS.each{ SO ->
					
					//println "$library - $SO - $ARCH - ${natives[(SO)][(ARCH)]}";
					
					def classifier = "natives-$SO";
					
					ZipUtils zutils = new ZipUtils()
					
					def zos = zutils.createZipFile(new File(targetBaseFile,"$library-${lwjglVersion}-${classifier}.jar"))
					zutils.addManifest(zos)
					natives[(SO)].each { file -> 
						def dir = new File(nativesBase,"${BasicConstants.basePath[(SO)]}")
						zutils.zipFile(new File(dir,file).getAbsoluteFile(),dir.getAbsolutePath(),zos)
					}
					zos.close()
					
					attached << classifier
				}
			}
			
			def mavenArtifactCoords = BasicConstants.mavenId[(library)]
			mavenArtifactCoords.version = lwjglVersion
			
			String pom = pomBuilder.buildPom(mavenArtifactCoords, attached, BasicConstants.mavenDependencies[(library)])
			
			
			def sources = BasicConstants.sources[(library)]
			if(sources!=null){
				def classifier = "sources"
				def sourceFile = sources.generateSources(sourceBase)
				FileUtils.copyFile(sourceFile,new File(targetBaseFile,"$library-${lwjglVersion}-${classifier}.jar"))
				attached << classifier
			}
			
			def javadoc = BasicConstants.javadoc[(library)]
			if(javadoc!=null){
				def classifier = "javadoc"
				def javadocFile = javadoc.generateJavadoc(javadocBase)
				FileUtils.copyFile(javadocFile,new File(targetBaseFile,"$library-${lwjglVersion}-${classifier}.jar"))
				attached << classifier
			}
			
			
			File pomFile = new File(targetBaseFile,"${library}-pom.xml")
			pomFile.write(pom);
			
			def libraryJar = new File(targetBaseFile,"$library-${lwjglVersion}.jar")
			FileUtils.copyFile(new File(jarsBase,"${library}.jar"),libraryJar)
			
			
			
			deployCommands << MavenDeployer.deploy(repoUrl, repoId, pomFile,libraryJar, null, targetBaseFile)
			attached.each{ classifier ->
				File artifactFile = new File(targetBaseFile,"$library-$mavenArtifactCoords.version-${classifier}.jar")
				
				deployCommands << MavenDeployer.deploy(repoUrl, repoId, pomFile, artifactFile, classifier, targetBaseFile)
			}
			
			installCommands << MavenDeployer.install(pomFile,libraryJar, null, targetBaseFile)
			attached.each{ classifier ->
				File artifactFile = new File(targetBaseFile,"$library-$mavenArtifactCoords.version-${classifier}.jar")
				
				installCommands << MavenDeployer.install(pomFile, artifactFile, classifier, targetBaseFile)
			}
		}
		
		File deployScriptLinux = new File(targetBaseFile,"deploy.sh")
		deployScriptLinux.text = deployCommands.join("\n")
		deployScriptLinux.setExecutable true
		
		File installScriptLinux = new File(targetBaseFile,"install.sh")
		installScriptLinux.text = installCommands.join("\n")
		installScriptLinux.setExecutable true
		logs.each { println it }
	}
}